using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Google.GData.Calendar;
using Google.GData.Client;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;

namespace GCalSync
{
    public partial class SyncForm : Form
    {
        public SyncForm()
        {
            InitializeComponent();
        }

        private void UpdateTestOutput(string output)
        {
            textBoxTestOutput.Text += output + Environment.NewLine;
            textBoxTestOutput.ScrollToCaret();
        }

        private void buttonTestSync_Click(object sender, EventArgs e)
        {
            textBoxTestOutput.Text = "";

            DateTime lastSync = GCalSync.Properties.Settings.Default.LastSync;
            UpdateTestOutput("Last Sync Time: " + lastSync.ToString());

            // Quick and dirty way to keep the user from double-syncing
            this.buttonTestSync.Enabled = false;

            // Set Options
            Core.GoogleCalendar.UserName = textBoxUsername.Text;
            Core.GoogleCalendar.Password = textBoxPassword.Text;
            Core.GoogleCalendar.QueryStartDate = DateTime.Now.AddDays(-28);
            Core.GoogleCalendar.QueryEndDate = DateTime.Now.AddMonths(6);

            UpdateTestOutput("Downloading from Google...");
            EventFeed calFeed = Core.GoogleCalendar.GetCalendarFeed();

            if (calFeed != null)
            {
                // Get Appointment/Calendar Folder.
                Outlook.MAPIFolder appFolder = Core.OutlookCalendar.GetCalendar();

                // Get all appointment items which have Google Properties
                Core.OutlookAppointments googledAppointments = new Core.OutlookAppointments(appFolder, true);
                
                // Get all appointments which are new since last sync (No Google Properties)
                Core.OutlookAppointments nonGoogledAppointments = new Core.OutlookAppointments(appFolder, false);

                // Load Google appointments into List.
                Core.GoogleAppointments googleAppointments = new Core.GoogleAppointments(calFeed.Entries);

                // update status bar
                UpdateTestOutput("Google -> Outlook");

                // add or update entries in outlook from google
                foreach (EventEntry googleEvent in googleAppointments)
                {
                    // Search in outlook for the appoitnment.
                    Outlook.AppointmentItem outlookAppointment = googledAppointments.GetById(googleEvent.Id.AbsoluteUri);
                    
                    // check to see if the appointment exists in Outlook. If not it will need to be 
                    // added other wise we will need to do sync check on it. 
                    if (outlookAppointment != null)
                    {
                        // Appointment is found, so go for the sync.
                        bool googleNewest = Core.SyncCheck.IsGoogleNewest(googleEvent, outlookAppointment);
                        bool outlookNewest = Core.SyncCheck.IsOutlookNewest(googleEvent, outlookAppointment);
                        bool changed = Core.SyncCheck.IsThereAChange(googleEvent, outlookAppointment);

                        if (changed && googleNewest)
                        {
                            Core.GoBetween.GoogleToOutlook(googleEvent, outlookAppointment);
                        }

                        if (changed && outlookNewest)
                        {
                            Core.GoBetween.OutlookToGoogle(outlookAppointment, googleEvent);
                        }

                        Util.AddCustomField(outlookAppointment, "GCalChecked", "1");

                    }
                    else
                    {
                        /// Potentiall a new item, need to run some logic to see if the item has been
                        /// deleted out of outlook.
                        /// Compare the update time of the google item to the last time the sync was run.
                        /// If the google item existed prior to the last run it should have been already synced.
                        /// so if it is no longer in outlook then it has been deleted out of outlook.
                        /// If the update is greater than then it is a new item from google.
                        if (DateTime.Compare(googleEvent.Updated.ToLocalTime(), lastSync) > 0)
                        {
                            // Appointment does not exist in Outlook, add it.
                            Core.GoBetween.AddGoogleToOutlook(googleEvent, GlobalObjects.outlookApplication);
                        }
                        else if (DateTime.Compare(googleEvent.Updated.ToLocalTime(), lastSync) < 0)
                        {
                            // This was in existance prior to the last sync. 
                            googleEvent.Delete();
                        }
                    }
                }

                
                foreach (Outlook.AppointmentItem oApp in googledAppointments)
                {
                    // this means it is google tagged but not in the feed pulled 
                    // down (out of time period or deleted) for the moment it is just 
                    // a delete of the item in outlook.
                    if (Core.GoBetween.GetCustomField(oApp, "GCalChecked") == "")
                    {
                        if (DateTime.Compare(Core.GoogleCalendar.QueryStartDate, oApp.CreationTime) < 0)
                            // delete in outlook.
                            oApp.Delete();

                    }
                }

                // Clean up for the next run.
                // Re get selection in case there has been a delete above. 
                googledAppointments = new Core.OutlookAppointments(appFolder, true);

                foreach (Outlook.AppointmentItem oApp in googledAppointments)
                    Core.GoBetween.AddCustomField(oApp, "GCalChecked", "");

                // add new outlook appointments to google
                foreach (Outlook.AppointmentItem oApp in nonGoogledAppointments)
                {
                    Core.GoBetween.AddOutlookToGoogle(oApp);
                }


            }


            // clear the status bar
            textBoxTestOutput.Text += "Updated: " + System.DateTime.Now.ToString() + Environment.NewLine;
            GCalSync.Properties.Settings.Default.LastSync = DateTime.Now;
            GCalSync.Properties.Settings.Default.Save();

            // Now we can allow the user to sync again if they so wish
            this.buttonTestSync.Enabled = true;

        }

        private void SyncForm_Load(object sender, EventArgs e)
        {
            this.textBoxUsername.Text = GCalSync.Properties.Settings.Default.Username;
            this.textBoxPassword.Text = GCalSync.Properties.Settings.Default.Password;


        }

        private void SyncForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            GCalSync.Properties.Settings.Default.Username = this.textBoxUsername.Text;
            GCalSync.Properties.Settings.Default.Password = this.textBoxPassword.Text;

            GCalSync.Properties.Settings.Default.Save();

        }

    }
}
